package com.bajiao.service.coupon.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bajiao.common.constant.CouponStatusEnum;
import com.bajiao.common.constant.StoreStatusEnum;
import com.bajiao.common.constant._Whole;
import com.bajiao.common.exception.DataHandleException;
import com.bajiao.common.util.DateUtils;
import com.bajiao.common.util.FastJsonHelper;
import com.bajiao.common.util.encryption.AesEncryptUtil;
import com.bajiao.common.util.oConvertUtils;
import com.bajiao.dto.store.QueryStoreDto;
import com.bajiao.dto.store.StoreDetailsRequest;
import com.bajiao.entity.coupon.Coupon;
import com.bajiao.entity.discountRule.DiscountRule;
import com.bajiao.entity.product.Product;
import com.bajiao.entity.store.Store;
import com.bajiao.entity.user.UserCoupon;
import com.bajiao.mapper.coupon.CouponMapper;
import com.bajiao.mapper.store.StoreMapper;
import com.bajiao.service.coupon.CouponService;
import com.bajiao.service.discountRule.DiscountRuleService;
import com.bajiao.service.store.StoreService;
import com.bajiao.service.user.UserCouponService;
import com.bajiao.service.visitor.VisitorService;
import com.bajiao.vo.coupon.CouponDetailsResponse;
import com.bajiao.vo.coupon.CouponResponse;
import com.bajiao.vo.store.StoreDetailsResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 优惠券表
 * @Author: FanJq
 * @Date:   2024-12-12
 * @Version: V1.0
 */
@Service
@Slf4j
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements CouponService {

    @Lazy
    @Resource
    private UserCouponService userCouponService;
    @Resource
    private VisitorService visitorService;
    @Resource
    private StoreService storeService;

    /**
     * @Description
     * 获取首页列表
     * @date 2024/12/12 15:30
     * @author FanJq
     * @param limit
     * @return {@link List< Coupon>}
    */
    @Override
    public List<CouponResponse> getIndexList(String userId, Integer limit) {
        List<Coupon> couponList = super.lambdaQuery()
                .eq(Coupon::getScope, _Whole.ONE)
                .eq(Coupon::getStatus, _Whole.ONE)
                .eq(Coupon::getReceiveWay, _Whole.THREE)
                .ge(Coupon::getEndTime, new Date())
                .orderByDesc(Coupon::getIsRecommend)
                .orderByDesc(Coupon::getCreateTime)
                .last("LIMIT " + limit)
                .list();
        return getCouponResponses(userId, couponList);
    }

    /**
     * @Description
     * 获取商家专属优惠券
     * @date 2024/12/13 15:15
     * @author FanJq
     * @param storeId
     * @return {@link List< Coupon>}
    */
    @Override
    public List<CouponResponse> getByStoreId(String userId, String storeId) {
        List<Coupon> couponList = super.lambdaQuery()
                .eq(Coupon::getStoreId, storeId)
                .eq(Coupon::getScope, _Whole.TWO)
                .eq(Coupon::getStatus, _Whole.ONE)
                .eq(Coupon::getReceiveWay, _Whole.THREE)
                .ge(Coupon::getEndTime, new Date())
                .orderByDesc(Coupon::getIsRecommend)
                .orderByDesc(Coupon::getCreateTime)
                .list();
        return getCouponResponses(userId, couponList);
    }

    /**
     * @Description
     * 获取优惠券列表
     * @date 2024/12/13 17:11
     * @author FanJq
     * @param userId
     * @param type 0-全部 1-专属券 2-折扣券 3-抵扣券
     * @return {@link List< CouponResponse>}
    */
    @Override
    public List<CouponResponse> getPage(String userId, Integer type) {
        LambdaQueryChainWrapper<Coupon> sqlQuery = super.lambdaQuery()
                .eq(Coupon::getStatus, _Whole.ONE)
                .eq(Coupon::getReceiveWay, _Whole.THREE)
                .ge(Coupon::getEndTime, new Date())
                .orderByDesc(Coupon::getIsRecommend)
                .orderByDesc(Coupon::getCreateTime);
        switch (type) {
            case 1:
                sqlQuery.eq(Coupon::getScope, _Whole.TWO);
                break;
            case 2:
                sqlQuery.eq(Coupon::getType, _Whole.ONE);
                break;
            case 3:
                sqlQuery.eq(Coupon::getType, _Whole.TWO);
                break;
        }
        List<Coupon> couponList = sqlQuery.list();
        return getCouponResponses(userId, couponList);
    }

    /**
     * @Description
     * 订单可用劵
     * @date 2024/12/13 17:27
     * @author FanJq
     * @param userId
     * @param storeId
     * @return {@link List< CouponResponse>}
    */
    @Override
    public List<CouponResponse> getOrderCouponPage(String userId, String storeId) {
        return userCouponService.getUserHasCoupon(userId, storeId);
    }

    /**
     * @Description
     * 获取优惠券详情
     * @date 2024/12/18 15:05
     * @author FanJq
     * @param userId
     * @param couponId
     * @return {@link CouponDetailsResponse}
    */
    @Override
    public CouponDetailsResponse getDetails(String userId, String couponId) {
        Coupon coupon = super.getById(couponId);
        if (ObjectUtil.isNull(coupon) || coupon.getStatus().intValue() == _Whole.ZERO)
            throw new DataHandleException("优惠券不存在");
        CouponDetailsResponse response = FastJsonHelper.beanToBean(coupon, CouponDetailsResponse.class);
        response.setQuota(coupon.getQuota().stripTrailingZeros().toPlainString());
//        if (response.getType() == _Whole.ONE) {
//            response.setQuota(coupon.getQuota().multiply(new BigDecimal("10")).setScale(2).stripTrailingZeros().toPlainString());
//        }
        if (StrUtil.isNotBlank(userId)) {
            UserCoupon usableCoupon = userCouponService.getUserUsableCoupon(userId, couponId);
            if (ObjectUtil.isNotNull(usableCoupon)) {
                response.setVerifyCode(usableCoupon.getVerifyCode());
                if (usableCoupon.getStatus().intValue() == _Whole.ONE) {
                    //@create by FanJq 2024/12/20 15:59 生成核销码
                    response.setVerifyQrCode(buildVerifyQrCode(response.getVerifyCode()));
                }
                response.setOrderNo(usableCoupon.getOrderNo());
                response.setIsHas(_Whole.ONE);
                response.setReceiveTime(usableCoupon.getReceiveTime());
                response.setExpireTime(usableCoupon.getExpireTime());
                return response;
            }
        }
        response.setReceiveTime(new Date());
        response.setExpireTime(DateUtils.addDay(response.getReceiveTime(), coupon.getDays()));
        if (coupon.getScope().intValue() == _Whole.TWO) {
            String storeTitle = storeService.getStoreTitle(coupon.getStoreId());
            response.setStoreTitle(storeTitle);
        } else {
            response.setStoreTitle("全平台");
        }
        //@create by FanJq 2024/12/18 16:33 处理浏览量
        this.addBrowse(couponId);
        return response;
    }

    /**
     * @Description
     * 处理销量
     * @date 2024/12/18 16:47
     * @author FanJq
     * @param couponId
     * @param flag
     * @return
    */
    @Override
    @Async("taskExecutor")
    public void salesLogic(String couponId, Integer flag) {
        //@create by FanJq 2024/12/18 16:47 递增浏览量
        LambdaUpdateChainWrapper<Coupon> updateSql = super.lambdaUpdate().eq(Coupon::getId, couponId);
        if (flag.intValue() == 1) {
            updateSql.setSql("sales = sales + 1");
        } else if (flag.intValue() == 2) {
            updateSql.setSql("sales = sales - 1");
        }
        updateSql.update();
    }


    @Resource
    private DiscountRuleService discountRuleService;
    @Resource
    private StoreMapper storeMapper;

    @Override
    public IPage<QueryStoreDto> getUseableStoreList(String couponId, Integer pageNumber, Integer pageSize) {

        Coupon coupon = super.getById(couponId);
        List<Store> storeList = new ArrayList<Store>();
        IPage<QueryStoreDto> page = new Page<>(pageNumber, pageSize);
        // 如果是20元优惠劵,则默认查找所有商家
        if(coupon.getPrice().intValue() == 20){
            storeList = storeService.list().stream()
                    .sorted(Comparator.comparing(Store::getId).reversed())
                    .skip((pageNumber - 1L) * pageSize).limit(pageSize)
                    .collect(Collectors.toList());
        }else{
            List<Coupon> list = this.list(new QueryWrapper<Coupon>().lambda()
                    .eq(Coupon::getPrice, coupon.getPrice())
                    .ne(Coupon::getStatus,StoreStatusEnum.CLOSE.getType().toString())
            );

            if(list.isEmpty()){
                return page;
            }
            List<String> storeIds = list.stream().map(Coupon::getStoreId).collect(Collectors.toList());
            storeList = (List) storeService.listByIds(storeIds);


            // 1. 查询店铺优惠规则中，根据优惠劵价格查询所有支持该价格的商家
//            List<BigDecimal> priceList= this.list(new QueryWrapper<Coupon>().lambda().eq(Coupon::getStatus, _Whole.ONE).eq(Coupon::getScope, 2))
//                    .stream().map(Coupon::getPrice).collect(Collectors.toList());
//            log.info("#####################1价格列表:{}", JSONUtil.parse(priceList));
            // 2. 获取店铺ID
//            List<String> storeIdList = discountRuleService.list(
//                    new QueryWrapper<DiscountRule>().lambda()
//                            .eq(DiscountRule::getMeet,coupon.getPrice()))
//                    .stream().map(DiscountRule::getStoreId).collect(Collectors.toList());
//
//            log.info("#####################2店铺ID:{}", JSONUtil.parse(storeIdList));
//            if(storeIdList.isEmpty()){
//                return null;
//            }
//
//            // 3. 询店铺列表
//            result = storeService.list(new QueryWrapper<Store>().lambda().in(Store::getId, storeIdList).ne(Store::getStatus, StoreStatusEnum.CLOSE.getType()))
//                    .stream()
//                    .sorted(Comparator.comparing(Store::getId).reversed())
//                    .skip((pageNumber - 1L) * pageSize).limit(pageSize)
//                    .collect(Collectors.toList());
//            log.info("#####################3店铺信息:{}", JSONUtil.parse(result));
        }

        List<QueryStoreDto> dtos = new ArrayList<>();
        storeList.stream().forEach(data -> {
            QueryStoreDto dto = new QueryStoreDto();
            BeanUtils.copyProperties(data, dto);

            // 营业状态、距离
            StoreDetailsResponse storeDetails = storeMapper.getStoreDetails(new StoreDetailsRequest(data.getLongitude(), data.getLatitude(), data.getId()));
            dto.setStatusConv(storeDetails.getStatusConv());
            dto.setDistance(storeDetails.getDistance() + "km");
            dtos.add(dto);
//            Coupon c = this.getOne(new QueryWrapper<Coupon>().lambda().eq(Coupon::getScope, 2).eq(Coupon::getStoreId, data.getId()).eq(Coupon::getPrice, coupon.getPrice()));

//            if(coupon.getPrice().intValue() == 20){
//                dto.setCount(-1); // -1表示不限量
//                BeanUtils.copyProperties(data, dto);
//                dtos.add(dto);
//            }else{
//                if(c != null){
//                    dto.setCount(c.getCount());
//                    BeanUtils.copyProperties(data, dto);
//                    dtos.add(dto);
//                }
//            }
        });
        page.setRecords(dtos);
        log.info("##############结果:{}", JSONUtil.parse(page));
        return page;
    }

    /**
     * @Description
     * 组装优惠券返回数据
     * @date 2024/12/13 17:02
     * @author FanJq
     * @param userId
     * @param couponList
     * @return {@link List< CouponResponse>}
    */
    private List<CouponResponse> getCouponResponses(String userId, List<Coupon> couponList) {
//        Map<String, String> storeTitleMap = new HashMap<>();
        List<CouponResponse> responseList = couponList.stream().map(coupon -> {
            CouponResponse response = FastJsonHelper.beanToBean(coupon, CouponResponse.class);
            response.setQuota(coupon.getQuota().stripTrailingZeros().toPlainString());
//            if (response.getType() == _Whole.ONE) {
//                response.setQuota(coupon.getQuota().stripTrailingZeros().toPlainString());
//            }
            if (StrUtil.isNotBlank(userId)) {
                UserCoupon usableCoupon = userCouponService.getUserUsableCoupon(userId, coupon.getId());
                if (ObjectUtil.isNotNull(usableCoupon)) {
                    response.setIsHas(_Whole.ONE);
                    response.setOrderNo(usableCoupon.getOrderNo());
                }
            }
//            if (coupon.getScope().intValue() == _Whole.TWO) {
//                if (!storeTitleMap.containsKey(coupon.getStoreId())) {
//                    String storeTitle = storeService.getStoreTitle(coupon.getStoreId());
//                    storeTitleMap.put(coupon.getStoreId(), storeTitle);
//                }
//                response.setStoreTitle(storeTitleMap.get(coupon.getStoreId()));
//            }
            return response;
        }).collect(Collectors.toList());
        return responseList;
    }

    /**
     * @Description
     *
     * @date 2024/12/18 16:34
     * @author FanJq
     * @param couponId
     * @return
    */
    private void addBrowse(String couponId) {
        //@create by FanJq 2024/12/13 10:21 递增浏览量
        super.lambdaUpdate().setSql("browse = browse + 1").eq(Coupon::getId, couponId).update();
        visitorService.record();
    }

    /**
     * @Description
     * 生成核销二维码
     * @date 2024/12/26 11:49
     * @author FanJq
     * @param verifyCode
     * @return {@link String}
     */
    private String buildVerifyQrCode(String verifyCode){
        Map<String, String> params = new HashMap<String, String>(){{
            put("a", "coupon");
            put("b", verifyCode);
            put("c", oConvertUtils.randomGen(3));
        }};
        String jsonString = JSONObject.toJSONString(params);
        String encrypt = AesEncryptUtil.encrypt(jsonString);
        return QrCodeUtil.generateAsBase64(encrypt, new QrConfig(), "png");
    }
}
